package org.example.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.example.constant.KeyConstant;
import org.example.dto.DictQueryDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class DictAspect {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 切入点
     * 切入点,基于注解实现的切入点  加上该注解的都是Aop切面的切入点
     */

    @Pointcut("@annotation(org.example.annotation.ClearAndReloadCacheDict)")
    public void pointCut() {

    }

    /**
     * 环绕通知
     * 环绕通知非常强大，可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值。
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     *
     * @param proceedingJoinPoint
     */
    @Around("pointCut()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        DictQueryDTO arg = (DictQueryDTO) proceedingJoinPoint.getArgs()[0];
        log.info("参数:{}", arg);
        //执行加入双删注解的改动数据库的业务 即controller中的方法业务
        Object proceed = null;
        try {
            proceed = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        //开一个线程 延迟1秒（此处是1秒举例，可以改成自己的业务）
        // 在线程中延迟删除  同时将业务代码的结果返回 这样不影响业务代码的执行
        new Thread(() -> {
            try {
                Thread.sleep(300);
                redisTemplate.delete(KeyConstant.REDIS_DICT_KEY + arg.getPageNum());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        return proceed;//返回业务代码的值
    }

}
